function isEmptyArray(arr) {
  if (!Array.isArray(arr) || arr.length === 0) {
    return true;
  }
  return false;
}

function arrayToTree(
  list,
  parent = { id: 0 },
  childAttr = 'id',
  parentAttr = 'parentId',
) {
  const treeNodes = [];
  const otherList = [];
  list.forEach((item) => {
    if (item[parentAttr] === parent[childAttr]) {
      treeNodes.push(item);
    } else {
      otherList.push(item);
    }
  });

  if (!isEmptyArray(treeNodes)) {
    treeNodes.forEach((child, index) => {
      // 递归算出 sub children
      const subList = arrayToTree(otherList, child, childAttr, parentAttr);
      if (!isEmptyArray(subList)) {
        treeNodes[index].children = subList;
      }
    });
  }
  return treeNodes;
}

function arrayToTreeIncludeSelf(
  list,
  parent = { id: 0 },
  childAttr = 'id',
  parentAttr = 'parentId',
) {
  const subTreeData = arrayToTree(list, parent, childAttr, parentAttr);
  const treeList = [];
  list.forEach((item) => {
    if (parent[childAttr] === item[childAttr]) {
      treeList.push({
        ...item,
        children: subTreeData,
      });
    }
  });
  return treeList;
}
const testList = [
  { id: 1, name: 'A', parentId: null },
  { id: 2, name: 'B', parentId: 1 },
  { id: 3, name: 'C', parentId: 1 },
  { id: 4, name: 'D', parentId: 2 },
  { id: 5, name: 'E', parentId: 3 },
];
console.log(testList);
console.log(JSON.stringify(arrayToTree(testList, { id: null }), null, 2));
